﻿using CommunicationTools.Helper;
using Masuit.Tools;
using Modbus.Device;
using Sunny.UI;
using System.IO.Ports;
using System.Runtime.CompilerServices;


namespace CommunicationTools.Controls
{
    public partial class ModbusRTUDemo : UIPage
    {

        public ModbusRTUDemo()
        {
            InitializeComponent();
            uiPipe1.Link(uiPipe2);
        }
        //功能码枚举
        public enum ModbusFunctionCodes
        {
            ReadCoils = 0x01,
            ReadDiscreteInputs = 0x02,
            ReadHoldingRegisters = 0x03,
            ReadInputRegisters = 0x04,
            /*            WriteSingleCoil = 0x05,
                        WriteSingleRegister = 0x06,
                        WriteMultipleCoils = 0x0F,
                        WriteMultipleRegisters = 0x10*/
        }

        ModbusFunctionCodes code;

        SerialPort serialPort = new SerialPort();
        IModbusSerialMaster master;
        private bool _isOpen = false;
        CancellationTokenSource _cts = new CancellationTokenSource();

        Random _rd1 = new Random();
        Random _rd2 = new Random();
        Random _rd3 = new Random();

        CancellationTokenSource _ctsRead = new CancellationTokenSource();
        CancellationTokenSource _ctsWrite = new CancellationTokenSource();

        //控制串口设置
        private void Enable(bool flag)
        {
            serial_Box.Enabled = flag;
            baudRate_Box.Enabled = flag;
            Pariy_box.Enabled = flag;
            Stopbit_Box.Enabled = flag;
            data_box.Enabled = flag;
            receive.Enabled = !flag;
        }
        //初始化串口设置
        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (string com in System.IO.Ports.SerialPort.GetPortNames())//自动获取串行口名称
            {
                serial_Box.Items.Add(com);
            }
            serial_Box.SelectedIndex = 0;


            baudRate_Box.SelectedIndex = 6;
            data_box.SelectedIndex = 0;

            receive.Enabled = false;
            Pariy_box.Items.AddRange(Enum.GetNames(typeof(Parity)));
            Pariy_box.SelectedIndex = 0;



            Stopbit_Box.Items.AddRange(Enum.GetNames(typeof(StopBits)));
            Stopbit_Box.SelectedIndex = 1;

            var functionCodes = Enum.GetValues(typeof(ModbusFunctionCodes));
            // 将枚举值添加到 ComboBox 控件中
            foreach (var value in functionCodes)
            {
                functionCode.Items.Add(value);
            }
            functionCode.SelectedIndex = 2;
        }









        private void btn_Open_Click(object sender, EventArgs e)
        {
            try
            {

                if (_isOpen)
                {
                    serialPort.Close();
                    btn_Open.Text = "打开";
                    LogBox.AppendText("连接关闭".FormatStringLog());
                    Enable(true);
                    _cts?.Cancel();
                }
                else
                {

                    serialPort.PortName = serial_Box.Text;
                    serialPort.BaudRate = baudRate_Box.Text.ToInt32();
                    serialPort.DataBits = data_box.Text.ToInt32();

                    if (Enum.TryParse(Pariy_box.Text, out Parity result))
                    {

                        serialPort.Parity = result;

                    }

                    if (Enum.TryParse(Stopbit_Box.Text, out StopBits stopBits))
                    {
                        if (stopBits != StopBits.None)
                        {
                            serialPort.StopBits = stopBits;
                        }
                    }

                    serialPort?.Open();


                    btn_Open.Text = "关闭";
                    Enable(false);
                    LogBox.AppendText("连接打开".FormatStringLog());
                }





            }
            catch (Exception exception)
            {
                btn_Open.Text = "打开";
                LogBox.AppendText(exception.Message.ToString().FormatStringLog());


            }
            finally
            {
                _isOpen = !_isOpen;
            }
        }


        //====================接收数据==========================================================================
        private void receive_Click(object sender, EventArgs e)
        {

            if (master == null)
            {
                master = ModbusSerialMaster.CreateRtu(serialPort);
            }
            try
            {
                var ch = (ModbusFunctionCodes)functionCode.SelectedItem;
                switch (ch)
                {
                    case ModbusFunctionCodes.ReadCoils:
                        ReadCoils();
                        break;
                    case ModbusFunctionCodes.ReadDiscreteInputs:
                        ReadInputs();
                        break;
                    case ModbusFunctionCodes.ReadInputRegisters:
                        ReadInputRegisters();
                        break;
                    case ModbusFunctionCodes.ReadHoldingRegisters:
                        ReadHoldingRegisters();
                        break;
                }
            }
            catch (Exception)
            {

                MessageBox.Show("功能码错误或者地址错误");
            }




        }

        private void ReadInputRegisters()
        {
            var result = master.ReadInputRegisters(device_box.Text.ToByte(), startingAddress.Text.ToUShort(), quantity.Text.ToUShort());
            if (result != null)
            {
                foreach (var c in result)
                {
                    LogBox.AppendText($"{c}".FormatStringLog());
                    LogBox.SelectionStart = LogBox.Text.Length;
                    LogBox.ScrollToCaret();
                }
            }
        }

        private void ReadInputs()
        {
            var result = master.ReadInputs(device_box.Text.ToByte(), startingAddress.Text.ToUShort(), quantity.Text.ToUShort());
            if (result != null)
            {
                foreach (var c in result)
                {
                    LogBox.AppendText($"{c}".FormatStringLog());
                    LogBox.SelectionStart = LogBox.Text.Length;
                    LogBox.ScrollToCaret();
                }
            }
        }

        private void ReadCoils()
        {
            var result = master.ReadCoils(device_box.Text.ToByte(), startingAddress.Text.ToUShort(), quantity.Text.ToUShort());
            if (result != null)
            {
                foreach (var c in result)
                {
                    LogBox.AppendText($"{c}".FormatStringLog());
                    LogBox.SelectionStart = LogBox.Text.Length;
                    LogBox.ScrollToCaret();
                }
            }
        }

        private void ReadHoldingRegisters()
        {
            var result = master.ReadHoldingRegisters(device_box.Text.ToByte(), startingAddress.Text.ToUShort(), quantity.Text.ToUShort());
            if (result != null)
            {
                foreach (var c in result)
                {
                    LogBox.AppendText($"{c}".FormatStringLog());
                    LogBox.SelectionStart = LogBox.Text.Length;
                    LogBox.ScrollToCaret();
                }
            }

        }


        //模拟开关
        private async void uiSwitch1_ActiveChanged(object sender, EventArgs e)
        {
            if (!serialPort.IsOpen) { uiSwitch1.Active = false; return; }
            else
            {
                for (int i = 1; i <= 14; i++)
                {
                    string pipeName = $"uiPipe{i}";
                    UIPipe uiPipe = (UIPipe)this.Controls.Find(pipeName, true).FirstOrDefault();

                    if (uiPipe != null)
                    {
                        // 设置控件的值
                        uiPipe.Active = true;
                    }
                }


            }

            if (uiSwitch1.Active)
            {
                timer1?.Start();
                if (master == null)
                {
                    master = ModbusSerialMaster.CreateRtu(serialPort);
                }
                _ctsRead = new CancellationTokenSource();
                _ctsWrite = new CancellationTokenSource();
              var SetTask=  SetValu(_ctsWrite.Token);
               var ReadTask = ReadValue(_ctsRead.Token);

               await Task.WhenAll(SetTask, ReadTask);
            }
            else
            {
                timer1?.Stop();
                _ctsRead?.Cancel();
                _ctsWrite?.Cancel();
            }

        }

        private async Task SetValu(CancellationToken cts)
        {
            try
            {
                await Task.Run(async () => {
                    ushort[] values = new ushort[3];
                    while (!cts.IsCancellationRequested)
                    {
                        values[0] = (ushort)_rd1.Next(34, 66);
                        values[1] = (ushort)_rd2.Next(34, 66);
                        values[2] = (ushort)_rd3.Next(34, 66);
                        master.WriteMultipleRegisters(1, 0, values);
                        await Task.Delay(1000);
                    }
                }, cts);
            }
            catch (Exception e)
            {

                Console.WriteLine(e.Message);
            }
           
        }

        private async Task ReadValue(CancellationToken cts)
        {
            try
            {
                await Task.Run(async () => {
                    ushort[] values = new ushort[3];
                    while (!cts.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        values = master.ReadHoldingRegisters(1, 0, 3);
                        Invoke(() => {
                            uiAnalogMeter1.Value = values[0];
                            uiLedLabel1.Text= values[0].ToString();
                            uiAnalogMeter2.Value = values[1];
                            uiLedLabel2.Text= values[1].ToString();
                            uiAnalogMeter3.Value = values[2];
                            uiLedLabel3.Text = values[2].ToString();                          
                        });

                    }

                }, cts);
            }
            catch (Exception e)
            {

                Console.WriteLine(e.Message);
            }
            

        }

        #region 管道
        private void uiValve1_ActiveChanged(object sender, EventArgs e)
        {
            uiPipe4.Active = uiValve1.Active;
        }

        private void uiValve2_ActiveChanged(object sender, EventArgs e)
        {
            uiPipe12.Active = uiPipe11.Active = uiPipe7.Active = uiPipe6.Active = uiPipe8.Active = uiPipe3.Active = uiPipe5.Active = uiValve2.Active;
        }

        private void uiValve3_ActiveChanged(object sender, EventArgs e)
        {
            uiPipe10.Active = uiValve3.Active;
        }

        private void uiValve4_ActiveChanged(object sender, EventArgs e)
        {
            uiPipe14.Active = uiPipe15.Active = uiValve4.Active;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (var pipe in this.GetControls<UIPipe>())
            {
                pipe.Invalidate();
                
            }
        }
        #endregion
    }
}
